/**
 * SimData 
 *
 * Manages map methods and data. Public methods are returned.
 *
 * @param Object map Google map object
 */
var SimData = function(map) {
	var map = map;
	var mapbounds;
	var allPolygons = [];
	var allPolylines = [];
	var startpoints = [];
	var endpoints = [];
	var rectangles = new google.maps.MVCArray();
	var findPathURI = "/findpath/";

	/**
	 * Return latitude and longitude coordinates on mouse move
	 */
	function getCoords() {
		google.maps.event.addListener(map, 'mouseover', function(e) {
			console.log(e.latLng);
		});
	}

	function getbounds(map) {
		console.log(map);
	}

	/**
	 * Remove marker from polyline and polygon. Update path and marker arrays.
	 * 
	 * @param Object params Path and marker arrays
	 */
	function removePolyMarker(params) {
		params.marker.setMap(null);
		for (var i = 0, I = params.markers.length; i < I && params.markers[i] != params.marker; ++i);
		params.markers.splice(i, 1);
		params.path.removeAt(i);
		params.markerlatLng.splice(i,1);
	}

	/**
	 * Create start/end point markers
	 * StyledMarker is from the google-maps-utility library
	 *
	 * @param Object options Object containing position, animation
 	 */
	function placeMarker(options) {
		var styledMarker = new StyledMarker({
			styleIcon: new StyledIcon(
				StyledIconTypes.BUBBLE, {
					color: options.color,
					text: options.text
				}),
			position: options.position,
			map: map,
			draggable: false
		});
	
		// Set parameters for removeMarker (scoping problems)
		var params = {
			marker: styledMarker,
			markers: startpoints,
			currentpos: options.position
		}; 

		// Push marker to appropriate array (start or endpoint)
		if (options.type === 'start') {
			//update our global list of startpoints
			startpoints.push(options.position);

			// On marker click, remove it current marker and update startpoints list
			google.maps.event.addListener(styledMarker, 'rightclick', function() { 
				removeMarker(params);
			});
		} else {
			endpoints.push(options.position);

			// Override parameter and set to endpoints
			params.markers = endpoints;
			google.maps.event.addListener(styledMarker, 'rightclick', function() { 
				removeMarker(params);
			});
		}
	}

	/**
	 * Remove a marker from the map/ and startpoints or endpoints arrays
	 * 
	 * @param Object param Clicked marker, marker array, clicked position
	 */
	function removeMarker(params) {
		params.marker.setMap(null); 
		for (var i = 0; i < params.markers.length; i++) {
			// Compare our array of starting points with the marker that was clicked on,
			// if they are the same, then remove that item from the array.
			if (params.markers[i].equals(params.currentpos)) { 
				params.markers.splice(i, 1);
			}
		}
	}

	/**
	 * Draw Rectangle
	 * New rectangles appear in the center of the map
	 */
	function drawRectangle() {
		var point1 = map.getCenter();
		//Second marker needs to be offset a bit to the northeast
		var point2 = add(point1, 0.0005);
		var marker1 = new google.maps.Marker({
			position: point1,
			map: map,
			draggable: true
		});
		var marker2 = new google.maps.Marker({
			position: point2,
			map: map,
			draggable: true
		});
		var rectangleOptions = {
			bounds: new google.maps.LatLngBounds(point1, point2),
			fillColor: "001111",
			map: map,
			strokeWeight: 2
		};

		google.maps.event.addListener(marker1, 'drag', redraw);
		google.maps.event.addListener(marker2, 'drag', redraw);

		var rectangle = new google.maps.Rectangle(rectangleOptions);
		rectangles.push(rectangle);

		/**
		 * add
		 * @param Object point LatLng object
		 * @param Float offset Value to add to latlng
		 * @return LatLng
		 */
		function add(point, offset) {
			var lat = parseFloat(point.lat() + offset);
			var lng = parseFloat(point.lng() + offset);
			var latlng = new google.maps.LatLng(lat, lng);
			return latlng;
		}

		/**
		 * redraw
		 * Set rectangle bounds to marker1 and marker2 current position
		 */
		function redraw() {
			var latLngBounds = new google.maps.LatLngBounds(
				marker1.getPosition(),
				marker2.getPosition()
			);
			rectangle.setBounds(latLngBounds);
		}
	}

	/**
	 * Public methods
	 */
	return {

		/**
		 * Draw polyline
		 * Paths in each polyline are appened to markerlatLng, each polyline is 
		 * pushed to allPolylines
		 */
		drawPolyline: function() {
			var markers = [];
			var polyLineOptions = {
				strokeColor: '#FF0000',
				strokeOpacity: 1.0,
				strokeWeight: 3,
			};

			polyline = new google.maps.Polyline(polyLineOptions);
			polyline.setMap(map);

			//Declare markerlatLng array to store the current polylines paths
			var markerlatLng = [];

			//Add the current polyline to the allPolylines property
			allPolylines.push(markerlatLng);

			google.maps.event.addListener(map, 'click', function(event) {
				var path = polyline.getPath();
				path.push(event.latLng);

				var marker = new google.maps.Marker({
					position: event.latLng,
					title: '#' + path.getLength(),
					map: map,
				});
				/*
				var marker = new StyledMarker({
					styleIcon: new StyledIcon(
						StyledIconTypes.MARKER, {
							color:"0000ff"
						}),
					position: event.latLng,
					map: map,
					draggable: false
				});
				*/
				markerlatLng.push({
					lat: event.latLng.lat(),
					lng: event.latLng.lng()
				});
		
				//markerlatLng.push(event.latLng);
				markers.push(marker);
			
				// Parameters for the removePolyMarker callback
				var params = { marker: marker, markers: markers, markerlatLng: markerlatLng, path: path };
				google.maps.event.addListener(marker, 'rightclick', function() {
					removePolyMarker(params);
				});
			});
		},

		/**
		 * Draw polygon
		 * Similar to drawPolyline
		 */
		drawPolygon: function() { 
			var markers = [];
			var path = new google.maps.MVCArray;
			var poly = new google.maps.Polygon({
				strokeWeight: 2,
				fillColor: "#5555FF"
			});

			poly.setMap(map);
			poly.setPaths(new google.maps.MVCArray([path]));

			var infowindow = new google.maps.InfoWindow({
				content: "HI"
			});

			//Declare markerlatLng array to store the current paths
			markerlatLng = [];

			//Add the current polygon to the allPolygons property
			allPolygons.push(markerlatLng);

			google.maps.event.addListener(map, 'click', function(event) {
				path.insertAt(path.length, event.latLng);
				var marker = new google.maps.Marker({
					position: event.latLng,
					map: map,
					draggable: true
				});

				markers.push(marker);
				marker.setTitle("#" + path.length);

				markerlatLng.push({
					lat: event.latLng.lat(),
					lng: event.latLng.lng()
				});

				// Click on a marker to remove that point
				// We have to send all of this data to the remove function due to scoping
				var params = { marker: marker, markers: markers, markerlatLng: markerlatLng, path: path };
				google.maps.event.addListener(marker, 'rightclick', function() {
					removePolyMarker(params);
				});

				google.maps.event.addListener(marker, 'dragend', function() {
					for (var i = 0, I = markers.length; i < I && markers[i] != marker; ++i);
					path.setAt(i, marker.getPosition());
				});
			});	
		},

		/**
		 * Directions request
		 *
		 * @param Object position Object containing origin and destination latLng objects
		 */
		directions: function(position) {
			var directionsService = new google.maps.DirectionsService();
			var directionsDisplay = new google.maps.DirectionsRenderer();

			directionsDisplay.setMap(map);

			var request = {
				origin: position.origin, 
				destination: position.dest,
				travelMode: google.maps.DirectionsTravelMode.DRIVING
			};

			directionsService.route(request, function(response, status) {
				if (status == google.maps.DirectionsStatus.OK) {

					console.log(response.routes[0].legs[0].distance.value);
					console.log(response.routes[0].legs[0].duration.value);

					directionsDisplay.setDirections(response);
				}
			});
		},

		/**
		 * placemarker
		 * Used to place markers for start and exit markers
		 *
		 * @param Object options Color, text, and position of marker
		 */
		placeMarker: function(options) { 
			placeMarker(options);
		},

		getPolygons: function() {
			return allPolygons;
		},

		getPolylines: function() {
			return allPolylines;
		},

		getEndpoints: function() {
			return endpoints;
		},

		getStartpoints: function() {
			return startpoints;
		},

		sendOverlays: function() {
			var mapbounds = {
				northeast: map.getBounds().getNorthEast(),
				southwest: map.getBounds().getSouthWest()
			};

			var data = {
				startpoints: startpoints,
				endpoints: endpoints,
				polygons: allPolygons,
				polylines: allPolylines,
				mapbounds: mapbounds
			};

			$.ajax({
				type: 'POST',
				url: findPathURI,
				data: JSON.stringify(data),
				success: function(data) {
					console.log(data);
				}
			});
		},

		getPolygonsTest: function() {
			polygons.forEach(function(item) {
				path = item.getPath();
				for (var i = 0; i < path.length; i++) {
					var coords = path.getAt(i);
					console.log('lat'+ coords.lat() + 'lng' + coords.lng());
				}
			});
		}
	};
};
